import multiprocessing
from types import FrameType
import signal
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from uvicorn import Config

from app.core.archive_monitor import ArchiveMonitor
from app.core.config import settings, global_vars
from app.core.plugin import PluginManager
from app.db.init import init_db, update_db, init_super_user
from app.command import Command
import uvicorn as uvicorn
from contextlib import asynccontextmanager

from app.scheduler import Scheduler


def init_routers():
    """
    初始化路由
    """
    from app.api.apiv1 import api_router
    # API路由
    App.include_router(api_router, prefix=settings.API_V1_STR)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    启动模块
    """
    # 初始化超级管理员
    init_super_user()
    # 监听档案变动
    ArchiveMonitor()
    # 加载插件
    PluginManager().start()
    # 启动定时服务
    Scheduler()
    # 启动事件消费
    Command()
    # 初始化路由
    init_routers()

    # 监听停止信号

    singal_handle()
    yield
    # 停止监听档案变动
    ArchiveMonitor().stop_monitor()
    # 停止插件
    PluginManager().stop()
    # 停止监听插件变更
    PluginManager().stop_monitor()

# App
App = FastAPI(title=settings.PROJECT_NAME,
              lifespan=lifespan,
              openapi_url=f"{settings.API_V1_STR}/openapi.json")

# 跨域
App.add_middleware(
    CORSMiddleware,
    allow_origins=settings.ALLOWED_HOSTS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# uvicorn服务
Server = uvicorn.Server(Config(App, host=settings.HOST, port=settings.PORT,
                               reload=settings.DEV, workers=multiprocessing.cpu_count()))


def singal_handle():
    """
    监听停止信号
    """

    def stop_event(signum: int, frame: FrameType):
        """
        SIGTERM信号处理
        """
        print(f"接收到停止信号：{signum}，正在停止系统...")
        global_vars.stop_system()
        Server.handle_exit(signum, frame)

    # 设置信号处理程序
    signal.signal(signal.SIGTERM, stop_event)
    signal.signal(signal.SIGINT, stop_event)


if __name__ == '__main__':
    # 初始化数据库
    init_db()
    # 更新数据库
    update_db()
    # 启动API服务
    Server.run()
